//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
// Opcode Decoder for M8051W/EW
// 
// $Log: m3s013dy.v,v $
// Revision 1.13  2002/03/12
// changed logic to be the same with VHDL the PC_CON[17] register has been
// eliminated
//
// Revision 1.12  2001/11/20
// First checkin of version 2 features and name change
//
// Revision 1.2  2001/10/31
// First parsable verilog for EW
//
// Revision 1.1.1.1  2001/07/17
// Re-imported E-Warp from Farnham filesystem
//
// Revision 1.11  2000/10/24
// Multiplier rewritten to improve power consumption.
// Code changes for Leonardo (ECN01372).
// Code changes for formal verification tools (ECN01410).
// MOVX @Ri page address controllable from PORT2I if I/O ports ommitted (ECN01387).
//
// Revision 1.10  2000/05/17
// ECN01354: SFRRE qualifiication
//
// Revision 1.9  2000/02/20
// NINT0/1 sampling and condition zero ALU timing optimisation
//
// Revision 1.8  2000/02/10
// Redundancy reduced for code coverage
//
// Revision 1.7  2000/02/05
// Name change repercussions
//
// Revision 1.6  1999/12/08
// Eliminate user instruction during state transition from interrupt service to
// debug state.
// RTL clean up of redundant declarations and sensitvity list entries.
//
// Revision 1.5  1999/11/30
// More debug changes.
//
// Revision 1.4  1999/11/12
// Debug mode fixes
//
// Revision 1.3  1999/11/09
// Write PS, TRAP, and EO degugging.
//
// Revision 1.2  1999/11/03
// Debug mode revisions.
//
// Revision 1.1.1.1  1999/10/28
// "initialization and source check-in for m8051e"
//
// Revision 1.1  1999/10/22
// Initial revision
//
////////////////////////////////////////////////////////////////////////////////

module m3s013dy (ALU_CON, SWITCH_CON, MEM_CON, SFR_CON, PC_CON, STATE_CON,
//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
                 IMM_CON, PORT_CON, INTR_CON, OPCODE);

  output [18:0] ALU_CON;
  output [5:0]  SWITCH_CON;
  output [15:0] MEM_CON;
  output [6:0]  SFR_CON;
  output [16:0] PC_CON;
  output [5:0]  STATE_CON;
  output        IMM_CON;
  output        PORT_CON;
  output        INTR_CON;
  input  [7:0]  OPCODE;

  reg    [18:0] ALU_CON;
  reg    [5:0]  SWITCH_CON;
  reg    [15:0] MEM_CON;
  reg    [6:0]  SFR_CON;
  reg    [16:0] PC_CON;
  reg    [5:0]  STATE_CON;
  reg           IMM_CON;
  reg           PORT_CON;
  reg           INTR_CON;
  reg           LO_0, LO_1, LO_2, LO_3, LO_4, LO_5, LO_4TOF, LO_5TOF, LO_6TOF;
  reg           HI_0, HI_1, HI_2, HI_3, HI_4, HI_5, HI_6, HI_7;
  reg           HI_8, HI_9, HI_A, HI_B, HI_C, HI_D, HI_E, HI_F;
  reg           MOVCS, MOVXS, ROTATES, RETURNS, MUL_DIV, XCHD;
  reg           CJNE, DJNZ, BIT_OPS;
  reg           ADD_XOR, SUBTRACT, PASS_OP_A, PASS_OP_B, INV_OP_A;

  // Shared sub-products, including high and low nibble value decoding
  always @(OPCODE) 
  begin: p_nibbles
    LO_4TOF    <= OPCODE[3] || OPCODE[2];
    LO_5TOF    <= OPCODE[3] || OPCODE[2] && |OPCODE[1:0];
    LO_6TOF    <= OPCODE[3] || &OPCODE[2:1];
    LO_0       <= OPCODE[3:0] == 4'h0;
    LO_1       <= OPCODE[3:0] == 4'h1;
    LO_2       <= OPCODE[3:0] == 4'h2;
    LO_3       <= OPCODE[3:0] == 4'h3;
    LO_4       <= OPCODE[3:0] == 4'h4;
    LO_5       <= OPCODE[3:0] == 4'h5;
    HI_0       <= OPCODE[7:4] == 4'h0;
    HI_1       <= OPCODE[7:4] == 4'h1;
    HI_2       <= OPCODE[7:4] == 4'h2;
    HI_3       <= OPCODE[7:4] == 4'h3;
    HI_4       <= OPCODE[7:4] == 4'h4;
    HI_5       <= OPCODE[7:4] == 4'h5;
    HI_6       <= OPCODE[7:4] == 4'h6;
    HI_7       <= OPCODE[7:4] == 4'h7;
    HI_8       <= OPCODE[7:4] == 4'h8;
    HI_9       <= OPCODE[7:4] == 4'h9;
    HI_A       <= OPCODE[7:4] == 4'ha;
    HI_B       <= OPCODE[7:4] == 4'hb;
    HI_C       <= OPCODE[7:4] == 4'hc;
    HI_D       <= OPCODE[7:4] == 4'hd;
    HI_E       <= OPCODE[7:4] == 4'he;
    HI_F       <= OPCODE[7:4] == 4'hf;
    MOVCS      <= OPCODE[7:5] == 3'b100 && OPCODE[3:0] == 4'h3;
    MOVXS      <= &OPCODE[7:5] && ~|OPCODE[3:2] && (OPCODE[1] || ~OPCODE[0]);
    ROTATES    <= OPCODE[7:6] == 2'b00  && OPCODE[3:0] == 4'h3; 
    RETURNS    <= OPCODE[7:5] == 3'b001 && OPCODE[3:0] == 4'h2;
    MUL_DIV    <= OPCODE[7:6] == 2'b10  && OPCODE[4:0] == 5'b00100;
    XCHD       <= OPCODE[7:4] == 4'hd && OPCODE[3:1] == 3'b011;
    CJNE       <= OPCODE[7:4] == 4'hb && |OPCODE[3:2];
    DJNZ       <= OPCODE[7:4] == 4'hd && (OPCODE[3] || OPCODE[2:0] == 3'b101);

    BIT_OPS    <= ~|OPCODE[3:0] && ((~|OPCODE[7:6] && |OPCODE[5:4]) ||
                                      OPCODE[7:5] == 3'b101)                  ||
                  OPCODE[3:0] == 4'h2 && (OPCODE[7:4] == 4'h7 || 
                                          (OPCODE[7] && ~&OPCODE[6:5]));
  end

  always @(LO_0 or LO_1 or LO_2 or LO_3 or LO_4 or LO_4TOF or LO_5TOF or
           HI_0 or HI_1 or HI_2 or HI_3 or HI_6 or HI_7 or HI_8 or HI_9 or
           HI_A or HI_B or HI_C or HI_D or HI_E or HI_F or OPCODE)
  begin: p_arith

    PASS_OP_A  <= LO_1                                                        ||
                  LO_2    && (HI_1 || HI_E)                                   ||
                  LO_3    && (HI_8 || HI_9 || HI_E)                           ||
                  LO_5TOF && (HI_8 || HI_A || HI_C || HI_E || HI_F);

    INV_OP_A   <= LO_0    && &OPCODE[6:5];

    PASS_OP_B  <= LO_4TOF && HI_7                                             ||
                  LO_0    && (HI_1 || ^OPCODE[6:5])                           ||
                  LO_2    && (HI_9 || HI_B || HI_C || HI_D);

    ADD_XOR    <= LO_4TOF && (HI_0 || HI_2 || HI_3 || HI_6)                   ||
                  OPCODE[1] && HI_6                                           ||
                  LO_4 && HI_D;

    SUBTRACT   <= LO_4TOF && (HI_1 || HI_9 || HI_B)                           ||
                  LO_5TOF && HI_D;
  end

  always @(LO_0 or LO_1 or LO_2 or LO_3 or LO_4 or LO_5 or LO_4TOF or LO_5TOF or
           LO_6TOF or HI_0 or HI_1 or HI_2 or HI_3 or HI_4 or HI_5 or HI_6 or
           HI_7 or HI_8 or HI_9 or HI_A or HI_B or HI_C or HI_D or HI_E or
           HI_F or MOVXS or MOVCS or ROTATES or RETURNS or MUL_DIV or CJNE or
           DJNZ or BIT_OPS or PASS_OP_A or PASS_OP_B or INV_OP_A or ADD_XOR or 
           SUBTRACT or XCHD or OPCODE)
  begin: p_decoder

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// ALU Controls for configuring module m3s003dy                               //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//
// ALU_CON(0 to 3) define the core ALU operation as follows
//
//   ALU_CON |  Operation
//   0 1 2 3 | 
// ----------+---------------------
//   0 0 0 0 |  return zero
//   1 1 0 0 |  bitwise invert operand A
//   0 1 1 1 |  bitwise OR B to A
//   0 1 0 1 |  bitwise EXOR A with B (addition)
//   0 0 1 1 |  pass operand A
//   0 0 1 0 |  bitwise AND A with B
//   1 0 1 0 |  subtract B from A
//   0 1 1 0 |  pass operand B
//
// ALU_CON(4) enables inter-bit carry.
// ALU_CON(5) enables inter-bit borrow.


  ALU_CON[0] <= LO_4    && HI_F                                               ||
                SUBTRACT                                                      ||
                INV_OP_A;
              
  ALU_CON[1] <= LO_4    && HI_F                                               ||
                (LO_4TOF || OPCODE[1]) && HI_4                                ||
                ADD_XOR                                                       ||
                PASS_OP_B                                                     ||
                INV_OP_A;

  ALU_CON[2] <= (LO_4TOF || OPCODE[1]) && (HI_4 || HI_5)                      ||
                SUBTRACT                                                      ||
                PASS_OP_B                                                     ||
                PASS_OP_A;
               
  ALU_CON[3] <= (LO_4TOF || OPCODE[1]) && HI_4                                ||
                ADD_XOR                                                       ||
                PASS_OP_A;
              
  ALU_CON[4] <= LO_4TOF && (HI_0 || HI_2 || HI_3)                             ||
                LO_4 && HI_D;

  ALU_CON[5] <= SUBTRACT;

// ALU_CON(6 to 9) define the ALU bit operation as follows
//
//   ALU_CON |  Operation
//   6 7 8 9 | 
// ----------+---------------------
//   0 0 0 0 |  return zero
//   1 1 0 0 |  NOT carry
//   0 1 1 1 |  CARRY OR BIT_OPERAND
//   0 0 1 0 |  CARRY AND BIT_OPERAND
//   1 0 1 1 |  CARRY OR NOT BIT_OPERAND
//   0 0 0 1 |  CARRY AND NOT BIT_OPERAND
//   0 0 1 1 |  pass CARRY
//   0 1 1 0 |  pass BIT_OPERAND
//   1 0 0 1 |  NOT BIT_OPERAND
//   1 1 1 1 |  return one

  ALU_CON[6] <= LO_0 && HI_A                                                  ||
                LO_2 && (HI_B || HI_D)                                        ||
                LO_3 && (HI_B || HI_D);

  ALU_CON[7] <= LO_2 && (HI_7 || HI_A || HI_D)                                ||
                LO_3 && (HI_B || HI_D);

  ALU_CON[8] <= LO_0 && HI_A                                                  ||
                LO_2 && (HI_7 || HI_8 || HI_9 || HI_A || HI_D)                ||
                LO_3 && HI_D;
              
  ALU_CON[9] <= LO_0 && (HI_A || HI_B)                                        ||
                LO_2 && (HI_7 || HI_9 || HI_B || HI_D)                        ||
                LO_3 && HI_D;

// Enable carry into bit 0 for ADDC and SUBB operations

  ALU_CON[10] <= LO_4TOF && (HI_3 || HI_9);

// Enable result bit to be switched back into source byte

  ALU_CON[11] <= LO_0 && HI_1                                                 ||
                 LO_2 && (HI_9 || HI_B || HI_C || HI_D);

// ALU output multiplexers controls
//
//  ALU_CON | ACCUMULATOR RESULT
// 14 13 12 |                   
// ---------+-------------------
//          |                   
//  0  0  0 | ALU_RESULT        
//  0  0  1 | XCH(OP_A, OP_B)   
//  0  1  0 | XCHD(OP_A, OP_B)  
//  0  1  1 | SWAP(OP_A)        
//  1  0  0 | MUL/DIV A RESULT  
//  1  0  1 | PROGRAM MEMORY DATA
//  1  1  0 | ROTATED A RESULT  
//  1  1  1 | EXTERNAL RAM DATA 

  ALU_CON[14] <= MUL_DIV || ROTATES || MOVCS || MOVXS;

  ALU_CON[13] <= XCHD                                                         ||
                 LO_4 && HI_C                                                 ||
                 ROTATES                                                      ||
                 MOVXS;

  ALU_CON[12] <= LO_4TOF && HI_C                                              ||
                 MOVXS || MOVCS;

// ALU result for register memory       
// ALU_CON | REGISTER RESULT              | OVERFLOW RESULT
//  16 15  |                              |
//  -------+---------------------------------------------------------
//         |                              |
//   0  0  | ALU_RESULT                   | ALU OVERFLOW
//   0  1  | XCHD(OP_A, OP_B)             | ALU OVERFLOW
//   1  0  | MUL/DIV B RESULT             | MULTIPLIER OVERFLOW
//   1  1  | PROGRAM ADDRESS TO BE SAVED  | MULTIPLIER OVERFLOW

  ALU_CON[16] <= MUL_DIV                                                      ||
                 LO_1 || OPCODE == 8'h12;
  ALU_CON[15] <= XCHD                                                         ||
                 LO_1 || OPCODE == 8'h12;

// ALU_CON| CARRY RESULT
//  18 17 |            
//  ------+-----------
//        |               
//   0  0 | ALU_CARRY 
//   0  1 | DAA CUMULATIVE CARRY
//   1  0 | BIT RESULT
//   1  1 | ROTATED CARRY  

  ALU_CON[18] <= ~|OPCODE[3:2];
  ALU_CON[17] <= LO_4 && HI_D                                                 ||
                 LO_3 && ~|OPCODE[7:6]; 

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// ALU OPERAND SWITCH CONTROL                                                 //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

// OPERAND_A may be one of: Accumulator (0), data memory (1), or an SFR (1).
// OPERAND_B may be one of: Immediate data (3), a number constant (4),
// or data memory or an SFR (2).

//    OPERAND_A selector

  SWITCH_CON[0]  <= ROTATES || LO_4 || XCHD                                   ||
                    LO_0 && OPCODE[7:5] == 3'b011                             ||
                    LO_2 && OPCODE[7:6] == 2'b01 && ~&OPCODE[1:0]             ||
                    LO_4TOF && (HI_2 || HI_3 || HI_4 || HI_5 ||
                                HI_6 || HI_9 || HI_C || HI_F)                 ||
                    OPCODE[7:1] == 7'b1011010;
  SWITCH_CON[1]  <= LO_5TOF && (HI_0 || HI_1 || HI_8 || HI_E)                 ||
                    LO_3 && OPCODE[7:6] == 2'b01                              ||
                    LO_6TOF && OPCODE[7:5] == 3'b101                          ||
                    HI_D && (OPCODE[3] || OPCODE[3:0] == 4'h5);
                   
//    OPERAND_B selector
  
  SWITCH_CON[2]  <= LO_0 && ~(&OPCODE[6:5] || HI_0)                           ||
                    LO_2 && |OPCODE[7:6]                                      ||
                    OPCODE == 8'hb5 || XCHD ||
                    LO_5TOF && (HI_2 || HI_3 || HI_4 || HI_5 ||
                               HI_6 || HI_9 || HI_C);
  SWITCH_CON[3]  <= LO_3 && ( ~OPCODE[7] && OPCODE[6] )                       ||
                    LO_4 && ( ~OPCODE[7] && |OPCODE[6:5] ||
                              {OPCODE[7:6], OPCODE[4]} == 3'b101)             ||
                    LO_5TOF && HI_7                                           ||
                    LO_6TOF && HI_B;
  SWITCH_CON[4]  <= LO_4TOF && OPCODE[7:5] == 3'b000                          ||
                    HI_D && (OPCODE[3] || OPCODE[2:1] == 2'b10);  
 
// SWITCH_CON[8] selects a numeric constant for possible use by the ALU
// The default numeric constant is one.

  SWITCH_CON[5]  <= LO_4 && HI_D;                 // select DAA adjustment value

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// DATA MEMORY INTERFACE CONTROL                                              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

// Data memory source address select, MEM_CON[4:0]
//    0:  program data
//    1:  stack pointer is the read address
//    2:  direct register address
//    3:  memory data forms indirect address
//    4:  bit operand address

  MEM_CON[1] <= RETURNS || LO_0 && HI_D;
  MEM_CON[2] <= OPCODE[3] && ~HI_A;
  MEM_CON[3] <= OPCODE[3:1] == 3'b011 && ~HI_A; 
  MEM_CON[4] <= BIT_OPS;
  MEM_CON[0] <= ~(RETURNS || LO_0 && HI_D || BIT_OPS || OPCODE[3] && ~HI_A ||
                OPCODE[3:1] == 3'b011 && ~HI_A) && |OPCODE;

// Data memory destination address select, MEM_CON[8:4]
//    5:  program data
//    6:  stack pointer is the write address
//    7:  direct register address
//    8:  memory data forms indirect address

  MEM_CON[6] <= LO_1 && OPCODE[4] || LO_2 && HI_1 || LO_0 && HI_C;
  MEM_CON[7] <= OPCODE[3] && ~HI_8;
  MEM_CON[8] <= OPCODE[3:1] == 3'b011 && ~HI_8; 
  MEM_CON[5] <= ~(LO_1 && OPCODE[4] || LO_2 && HI_1 || LO_0 && HI_C ||
                  BIT_OPS || OPCODE[3] && ~HI_8 || OPCODE[3:1] == 3'b011 &&
                  ~HI_8) && |OPCODE;

// Signal a second memory read address for RETurn instructions
  MEM_CON[9] <= RETURNS;

// Control for data memory and SFR write strobes

// MEM_CON  |  Memory/SFR write time
// 10 11 12 |
// ---------+----------------------------------------
//  0  0  0 |  No write back using memory interface
//  1  0  0 |  End of phase 2 of last machine cycle
//  0  1  0 |  End of phase 2 of first machine cycle, CALLs and PUSHes
//  0  0  1 |  End of phase 1 of second machine cycle, CALLs

  MEM_CON[10] <= LO_5TOF &&
                       (HI_0 || HI_1 || HI_7 || HI_8 || HI_C || HI_D || HI_F) ||
                 LO_6TOF && HI_A                                              ||
                 LO_0 && (HI_1 || HI_D)                                       ||
                 LO_3 && (HI_4 || HI_5 || HI_6)                               ||
                 LO_2 && (HI_4 || HI_5 || HI_6 || HI_9 || HI_B || HI_C || HI_D);

  MEM_CON[11] <= LO_0 && HI_C || LO_1 && OPCODE[4] || LO_2 && HI_1;

  MEM_CON[12] <= LO_1 && OPCODE[4] || LO_2 && HI_1;

  MEM_CON[13] <= LO_5 && HI_8;              

// Destination write is conditional, used by JBC instruction.
  MEM_CON[14] <= LO_0 && HI_1;

// Direct memory read
  MEM_CON[15] <= LO_0 && (HI_1 || HI_2 || HI_3 || HI_A || HI_B || HI_C)       ||
                 LO_2 && |OPCODE[7:6] && ~&OPCODE[7:5]                        ||
                 LO_3 && (HI_4 || HI_5 || HI_6)                               ||
                 LO_5 && ~(HI_7 || HI_A || HI_F)                              ||
                 LO_6TOF && HI_A;

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// CORE SFR WRITE CONTROLS                                                    //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//
// SFR_CON is the opcode-decoded controls for the core SFRs: ACC, B, PSW and
// STACK_POINTER.
// Their function is to provide the opcode-intrinsic load signals which
// are in addition to any general SFR write operation.
//
// SFR_CON |   Function
// -----------------------------------------------------
//    0    |  load accumulator at end of last cycle
//    1    |  load accumulator at end of cycle 2 phase 1
//    2    |  load B register
//    3    |  load carry flag
//    4    |  load auxilliary carry flag
//    5    |  load overflow flag
//    6    |  load accumulator from external data memory

  SFR_CON[0] <= LO_4 && ~HI_B                                                 ||
                LO_5TOF && (HI_2 || HI_3 || HI_4 || HI_5 || HI_6 || HI_9 ||
                            HI_C || HI_E)                                     ||
                OPCODE[7:1] == 7'b1101011 || ROTATES;
  SFR_CON[1] <= MOVCS;
  SFR_CON[2] <= MUL_DIV;
  SFR_CON[3] <= ROTATES && OPCODE[4] || MUL_DIV || OPCODE == 8'hd4    ||
                LO_4TOF && (HI_2 || HI_3 || HI_9 || HI_B )            ||
                LO_0 && OPCODE[7:5] == 3'b101                         ||
                LO_2 && (HI_7 || {OPCODE[7:6], OPCODE[4]} == 3'b100)  ||
                LO_3 && (OPCODE[7:5] == 3'b110 || HI_B);
  SFR_CON[4] <= LO_4TOF && (HI_2 || HI_3 || HI_9);
  SFR_CON[5] <= LO_4TOF && (HI_2 || HI_3 || HI_9) || MUL_DIV;
  SFR_CON[6] <= MOVXS && ~OPCODE[4];

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// PROGRAM MEMORY INTERFACE CONTROLS                                          //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//
// Control PC Increment times

  // Increment program counter at cycle 1, phase 2.
  PC_CON[0] <= LO_0    && (HI_1 || HI_2 || HI_3 || HI_9)                      ||
               LO_1                                                           ||
               LO_2    && (~|OPCODE[7:5] || HI_A || HI_B || HI_C || HI_D)     ||
               LO_4    && (HI_2 || HI_3 || HI_7 || HI_9)                      ||
               LO_4TOF && (HI_7  || HI_B)                                     ||
               LO_5    && ~HI_A                                               ||
               (LO_2 || LO_3 || LO_4) && (HI_4 || HI_5 || HI_6);

  // Increment program counter at cycle 2, phase 1.
  PC_CON[1] <= LO_0    && (HI_1 || HI_2 || HI_3 || HI_4 || HI_5 || HI_6 ||
                           HI_7 || HI_8)                                      ||
               LO_2    && HI_1                                                ||
               CJNE || DJNZ;

  // Increment program counter at cycle 2, phase 2.
  PC_CON[2] <= LO_0    && (HI_9 || HI_A || HI_B || HI_C || HI_D)              ||
               LO_2    && (HI_7 || HI_8 || HI_9)                              ||
               LO_3    && (HI_4 || HI_5 || HI_6)                              ||
               LO_5    && (HI_7 || HI_8)                                      ||
               LO_6TOF && (HI_8 || HI_A);

  // Data pointer operations
  PC_CON[3]  <= LO_3 && (HI_9 || HI_A);                     // DPTR arithmetic
  PC_CON[4]  <= LO_3 && HI_7;                               // JMP @A+DPTR
  PC_CON[12] <= LO_0 && HI_9;                               // MOV DPTR, #16
  PC_CON[14] <= LO_3 && HI_A;                               // INC DPTR
  PC_CON[6]  <= LO_5 && HI_A;                               // MOVC @(DPTR++), A

  // Select the 8-bit operand for certain MOVC and MOVX instructions
  PC_CON[5]  <= (LO_2 || LO_3) && (HI_E || HI_F);           // MOVX @Ri ops

  // Relative Jump Controls
  PC_CON[7] <= LO_0 && ~OPCODE[7] && ~HI_0                                    ||
               LO_4TOF && HI_B                                                ||
               (LO_5 || OPCODE[3]) && HI_D;
  PC_CON[8] <= LO_0 && HI_8;

  // PC ALU output MUX selectors
  PC_CON[9]  <= LO_2 && (~|OPCODE[7:5]);                // LJMP or LCALL
  PC_CON[10] <= LO_1;                                   // 11-bit operations
  PC_CON[11] <= RETURNS;                                // src PC from data mem
  PC_CON[15] <= LO_0 && (HI_E || HI_F);                 // MOVX / MOVC @DPTR
  PC_CON[16] <= LO_1 && OPCODE[4] || LO_2 && HI_1;      // CALLS

  // Miscellaneous extra sources of program registers loads
  PC_CON[13] <= MOVCS;

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// State machine cycle count control
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//
//
// STATE_CON | Function
// ----------+----------------------------------------------------
//      0    | Two cycle instruction
//      1    | Four cycle instruction
//      2    | Read program memory at end C1P1
//      3    | Read program memory at end C1P2
//      4    | Read program memory at end C2P1
//      5    | Access external data memory

  STATE_CON[0] <= LO_0 && |OPCODE[7:4]                                        ||
                  LO_1                                                        ||
                  LO_2 && (~|OPCODE[7:6] || HI_7 || HI_9 || HI_E || HI_F)     ||
                  LO_3 && (OPCODE[7:6] == 2'b01 || HI_9 || HI_A || HI_E || HI_F)
                                                                              ||
                  LO_5 && (HI_7 || HI_A)                                      ||
                  LO_6TOF && HI_A                                             ||
                  HI_8 || MUL_DIV || CJNE || DJNZ;
                  
  STATE_CON[1] <= MUL_DIV;

  STATE_CON[2] <= LO_0 && (HI_1 || HI_2 || HI_3 || HI_4 || HI_9 || HI_A ||
                           HI_B || HI_C || HI_D)                              ||
                  LO_1                                                        ||
                  LO_2 && ~HI_2 && ~HI_3 && ~HI_E && ~HI_F                    ||
                  LO_3 && (HI_4 || HI_5 || HI_6)                              ||
                  LO_4 && (~OPCODE[7] && |OPCODE[6:5] || HI_9 || HI_B)        ||
                  LO_5 && ~HI_A                                               ||
                  LO_6TOF && (HI_7 || HI_8 || HI_A || HI_B);

  STATE_CON[3] <= LO_0 && (~OPCODE[7] || ~|OPCODE[6:5])                       ||
                  LO_2 && ~|OPCODE[7:5]                                       ||
                  LO_3 && (HI_4 || HI_5 || HI_6)                              ||
                  LO_4 && HI_B                                                ||
                  LO_5 && (HI_7 || HI_8 || HI_B || HI_D)                      ||
                  LO_6TOF && (HI_B || HI_D && OPCODE[3]);

  STATE_CON[4] <= MOVCS;
  STATE_CON[5] <= MOVXS;

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// IMMEDIATE REGISTER NUMBER 1 load time control                              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//
// When true, the immediate register is loaded at C2P1 instead of the default 
// time of C1P2.
//
  IMM_CON <= LO_3 || LO_5 && HI_7;

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// PORT READ SOURCE CONTROL - switches between sampled port pins and port SFRs//
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//
// When set PORT_CON causes the port SFR values to be used as operands
//
  PORT_CON <= LO_0 &&  HI_1                                                   ||
              LO_2 && (HI_4 || HI_5 || HI_6 || HI_9 || HI_B || HI_C || HI_D)  ||
              LO_3 && (HI_4 || HI_5 || HI_6)                                  ||
              LO_5 && (HI_D || ~|OPCODE[7:5]);
          
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// INTERRUPT CONTROL - RETI is decoded for synchronising the state machine;   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//
  INTR_CON <= LO_2 &&  HI_3;

  end
endmodule
